home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Programming / RxSocket / Examples / ping.rexx < prev    next >
Encoding:
OS/2 REXX Batch file  |  2001-09-18  |  6.1 KB  |  185 lines

  1. /*
  2.  *
  3.  * This code is NOT from Berkley, but FROM ME :-)
  4.  *
  5.  * Very stupid Arexx ping.
  6.  * Don't use it to ping localhost or you would ROTFL.
  7.  *
  8.  * Usage: ping <HOST> [SIZE/N] [NUM/N] [QUICK/S]
  9.  *
  10.  * HOST - the host name to ping
  11.  * SIZE - the size of the imcp echo packet
  12.  * NUM   - the number of packet to send - 0 means continuos
  13.  * QUICK - don't delay, send as fast as possible
  14.  *
  15. */
  16.  
  17. signal on halt
  18. signal on break_c
  19.  
  20. call init()
  21. call start()
  22. signal break_c
  23.  
  24. /********************************************************************/
  25. init: procedure expose global.
  26.     l="rmh.library";if ~show("L",l) then;if ~addlib(l,0,-30) then exit
  27.     if AddLibrary("rexxsupport.library","rxsocket.library")~=0 then exit
  28.     global.prg = ProgramName("NoExt")
  29.  
  30.     /** read and parse arguments **/
  31.     template="HOST/A,SIZE/K/N,NUM/K/N,QUICK/S"
  32.     help="
  33. ping 2.0 by Alfonso Ranieri" || "a"x || "
  34. Usage:" global.prg "<HOST> [SIZE/K/N] [NUM/K/N] [QUICK/S] [HELP/S] [VERSION/S]" || "a"x || "
  35.     HOST    the host to ping" || "a"x || "
  36.     SIZE    the SIZE of the packet to send (7<SIZE<8000)" || "a"x || "
  37.     NUM     how many packet" || "a"x || "
  38.     QUICK   sends packet as fatest as possible" || "a"x
  39.  
  40.     if ~RMH_ReadArgs(template,help) then do
  41.         call PrintFault()
  42.         exit
  43.     end
  44.  
  45.     if parm.1.flag then
  46.         if parm.1.value>7 & parm.1.value<8000 then global.dataSize=parm.1.value
  47.         else call err("SIZE must be >7 and <8000")
  48.     else global.dataSize=56
  49.  
  50.     if parm.2.flag then
  51.         if parm.2.value>0 then global.numPkt=parm.2.value
  52.         else call err("NUM must be positive")
  53.     else global.numPkt=1E10
  54.  
  55.     global.wait=~parm.3.flag
  56.  
  57.     global.break=0
  58.  
  59.     /** resolve host name **/
  60.     global.host=parm.0.value
  61.     global.sin.addrAddr=resolve(global.host)
  62.     if global.sin.addrAddr=="-1" then call err "host <"global.host"> not found"
  63.  
  64.     /** create a RAW ICMP socket **/
  65.     global.sock=socket("INET","RAW","ICMP")
  66.     if global.sock<0 then call err("no socket")
  67.  
  68.     /** socket must NOT blocking **/
  69.     call IOCtlSocket(global.sock,"FIONBIO",1)
  70.  
  71.     /** we need an ID to recognize our icmp **/
  72.     global.ourID=right(x2c(pragma("ID")),2)
  73.  
  74.     /** init globals */
  75.     global.min=1E10
  76.     global.max=0
  77.     global.avg=0
  78.     global.nrec=0
  79.     global.ntrans=0
  80.  
  81.     /** create a timer **/
  82.     global.tim=CreateTimer()
  83.     global.ts=TimerSignal(global.tim)
  84.  
  85.     return
  86. /********************************************************************/
  87. start: procedure expose global.
  88.     if global.numPkt==1E10 then global.ps=""
  89.     else global.ps=" Num:" global.numPkt
  90.     say global.PRG global.host "("global.sin.addrAddr"):" global.dataSize "data bytes" global.ps
  91.  
  92.     /** Here we go:
  93.         wait_for_packet_or_time_to_send
  94.         readpacket if any
  95.         sendpacket if time
  96.     **/
  97.  
  98.     call StartTimer(global.tim,global.wait)
  99.     call sendPacket
  100.     global.sel.read.0=global.sock
  101.     go=global.ntrans<global.numPkt | global.numPkt==1
  102.     do while go
  103.  
  104.         res=WaitSelect("global.sel",,,global.ts)
  105.         if res~=0 then call readPacket
  106.  
  107.         if and(global.sel.signals,global.ts)~=0 then do
  108.             call sendPacket
  109.             if global.wait==0 then call WriteCH("STDOUT",".")
  110.             call StartTimer(global.tim,global.wait)
  111.         end
  112.         go=global.ntrans<global.numPkt
  113.     end
  114.     return
  115. /********************************************************************/
  116. err: procedure expose global.
  117. parse arg msg
  118.     say global.prg":" msg
  119.     exit
  120. /********************************************************************/
  121. pad: procedure
  122. parse arg string,len
  123.     return copies(d2c(0),len-length(string)) || string
  124. /********************************************************************/
  125. d2m: procedure
  126. parse arg val,len
  127.     return pad(d2c(val),len)
  128. /********************************************************************/
  129. sendPacket: procedure expose global.
  130.     /** here we create an ICMP echo packet **/
  131.     pktf = global.ourID || d2m(global.ntrans,2)
  132.     call GetSysTime("TV")
  133.     pktf=pktf || d2m(tv.secs,4) || d2m(tv.micro,4) || copies("0"x,global.dataSize-8)
  134.     temp="0800"x || "0000"x || pktf
  135.     pkt="0800"x || d2c(InetCksum(temp)) || pktf
  136.     if sendto(global.sock,pkt,0,"global.sin")<0 then call err("sendto error ("ErrorString()")")
  137.     global.ntrans=global.ntrans+1
  138.     return
  139. /********************************************************************/
  140. readPacket: procedure expose global.
  141.     /** here we read an ICMP packet and check if it is an ICMP
  142.         echo-replay for us **/
  143.     call GetSysTime("NOW")
  144.     res=recvfrom(global.sock,"BUFF",256)
  145.     if res<0 then call call err("recvfrom error ("ErrorString()")")
  146.     parse var buff vhl +1 tos +1 len +2 id +2 off +2 ttl +1 rest
  147.     hl=c2d(bitand(vhl,'F'x))*8
  148.     buff=c2x(buff)
  149.     parse var buff +hl type +2 code +2 cksum +4 id +4 seq +4 s +8 m +8 data
  150.     if c2d(len)~=global.dataSize+8 | type~='00' | code~='00' | id~=c2x(global.ourID)
  151.         then return
  152.     old.secs=x2d(s)
  153.     old.micro=x2d(m)
  154.     call SubTime("NOW","OLD")
  155.     time=now.secs*1000000+now.micro
  156.     time=time%1000"."time//1000
  157.     time=((time*100)%1)/100
  158.     if global.wait==1 then
  159.         say c2d(len) "bytes from" global.sin.AddrAddr": icmp_seq="x2d(seq) "ttl="c2d(ttl) "time="time "ms"
  160.     global.nrec=global.nrec+1
  161.     if time>global.max then global.max=time
  162.     if time<global.min then global.min=time
  163.     global.avg=global.avg+time
  164.     return
  165. /********************************************************************/
  166. /** statistics **/
  167. halt:
  168. break_c:
  169.     if break==1 | sigl<38 then call err("user break")
  170.     if t~="T" then call StopTimer(global.tim)
  171.     break=1
  172.     signal on break_c
  173.     if global.ntrans>global.nrec & global.max>0 then do
  174.         res=WaitSelect("global.sel",5)
  175.         if res~=0 then call readPacket
  176.     end
  177.     if ntrans==0 then loss=100
  178.     else loss=(global.ntrans-global.nrec)/global.ntrans*100
  179.     say
  180.     say "---" global.host "ping statistics ---"
  181.     say global.ntrans "packets transmitted," global.nrec "packets received," loss"% packet loss"
  182.     if global.nrec>0 then say "round-trip min/avg/max =" global.min"/"|| (((global.avg/global.nrec)*100)%1)/100 || "/"global.max "ms"
  183.     exit
  184. /********************************************************************/
  185.